#include <vector>
#include <mutex>
#include <thread>
#include <chrono>
#include <random>
#include <functional>



namespace raft{
struct VoteRequest {
    int nodeId;
    int term;
};
struct VoteResponse {
    int nodeId;
    int term;
    bool voteGranted;
};
struct HeartbeatRequest {
    int nodeId;
    int term;
};
struct HeartbeatResponse {
    int nodeId;
    int term;
};

enum Role{
    FOLLOWER,
    CANDIDATE,
    LEADER
};

enum State{
    RUNNING,

    STOPPED
};

class ElectionThread{
public:
    static void Election(Raft& raft, int term)
    {
        {
            std::lock_guard<std::mutex> lock(raft.mutex_raft_info_);
            for (int nodeId : raft.nodes_)
            {
                if (nodeId == raft.nodeId_)
                {
                    voteSize_++;
                    continue;
                }
                VoteRequest voteRequest;
                voteRequest.nodeId = raft.nodeId_;
                voteRequest.term = term;
                if (raft.role_ != CANDIDATE || raft.currentTerm_ != term)
                {
                    return;
                }
                raft.sendVoteRequest(nodeId, voteRequest, voteSize_); // async send
            }
        }

    }
    ElectionThread(Raft& raft, int term)
    {
        raft_ = &raft;
        term_ = term;
        voteSize_ = 0;
    }
    void start()
    {
        thread_ = std::thread(ElectionThread::Election, std::ref(*raft_), term_);
    }
    void join()
    {
        thread_.join();
    }
private:
    Raft* raft_;
    std::thread thread_;
    int term_;
    int voteSize_;
};
class Raft{
public:

    static void ElectionTimeoutThread(Raft& raft)
    {
        while (raft.state_ == RUNNING)
        {
            {
                std::lock_guard<std::mutex> lock(raft.mutex_raft_info_);
                if (raft.role_ == LEADER)
                {
                    continue;
                }
                if (raft.isElectionTimeoutNeedLocked())
                {
                    raft.becomeCandidateNeedLocked();
                    ElectionThread(raft, raft.currentTerm_).start();
                }
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(rand() % (maxElectionTimeout_ - minElectionTimeout_)));
        }
    }
    Raft(int nodeId, std::vector<int> nodes){
        nodeId_ = nodeId;
        nodes_ = nodes;
        currentTerm_ = 0;
        votedFor_ = -1;
        maxElectionTimeout_ = 2000;
        minElectionTimeout_ = 1000;
        role_ = FOLLOWER;
        leaderId_ = -1;
    }
    void start(){
        {
            std::lock_guard<std::mutex> lock(raft.mutex_raft_info_);
            state_ = RUNNING;
            electionTimeoutThread_ = std::thread(Raft::ElectionTimeoutThread, std::ref(*this));
            electionTimeoutStart_ = std::chrono::steady_clock::now();
        }
        electionTimeoutThread_.start();

        electionTimeoutThread_.join();
    }
    void stop();

    bool isElectionTimeoutNeedLocked()
    {
        return electionTimeout_ > electionTimeoutStart_;
    }
    void resetElectionTimeoutNeedLocked()
    {
        electionTimeout_ = getRandomElectionTimeoutNeedLocked();
    }
    

    void becomeFollowerNeedLocked(int term)
    {
        if (term < currentTerm_)
        {
            return;
        }
        role_ = FOLLOWER;
        if (term > currentTerm_)
        {
            votedFor_ = -1;
        }
        currentTerm_ = term;

    }
    void becomeCandidateNeedLocked()
    {
        if (role_ == LEADER)
        {
            return;
        }
        currentTerm_++;
        votedFor_ = nodeId_;
        role_ = CANDIDATE;
    }
    void becomeLeaderNeedLocked()
    {
        if (role_ != CANDIDATE)
        {
            return;
        }
        role_ = LEADER;
        leaderId_ = nodeId_;
    }
    int getRandomElectionTimeoutNeedLocked()
    {
        return rand() % (maxElectionTimeout_ - minElectionTimeout_) + minElectionTimeout_;
    }
    void sendVoteRequest(int nodeId, VoteRequest voteRequest, int& voteSize)
    {
        VoteResponse voteResponse;
        // 获取response
        {
            std::lock_guard<std::mutex> lock(mutex_raft_info_);
            if (currentTerm_ < voteRequest.term)
            {
                becomeFollowerNeedLocked(voteRequest.term);
                return;
            }
            if (currentTerm_ > votedRequest.term || role_ != CANDIDATE)
            {
                return;
            }
            if (voteResponse.voteGranted)
            {
                voteSize++;
                if (voteSize > nodes_.size() / 2)
                {
                    becomeLeaderNeedLocked();
                    heartbeat(currentTerm_);
                    return;
                }
            }

        }
        // async send
    }
    void receiveVoteRequest(VoteRequest voteRequest)
    {
        {
            std::lock_guard<std::mutex> lock(mutex_raft_info_);
            if (currentTerm_ > voteRequest.term)
            {
                return;
            }
            VoteResponse voteResponse;
            if (currentTerm_ < voteRequest.term)
            {
                becomeFollowerNeedLocked(voteRequest.term);
            }
            if (votedFor_ != -1)
            {
                return;
            }
            votedFor_ = voteRequest.nodeId;
            voteResponse.voteGranted = true;
            voteResponse.term = currentTerm_;
            voteResponse.nodeId = nodeId_;
            sendVoteResponse(voteResponse);
            resetElectionTimeoutNeedLocked();

        }
    }
    void sendVoteResponse(VoteResponse voteResponse){}
    void heartbeat(int term){
        {
            std::lock_guard<std::mutex> lock(mutex_raft_info_);
            if (role_ != LEADER || currentTerm_ != term)
            {
                return;
            }
            for (int nodeId : nodes_)
            {
                if (nodeId == nodeId_)
                {
                    continue;
                }
                HeartbeatRequest heartbeatRequest;
                heartbeatRequest.nodeId = nodeId_;
                heartbeatRequest.term = currentTerm_;
                sendHeartbeatRequest(nodeId, heartbeatRequest);
            }

        }
    }
    void sendHeartbeatRequest(int nodeId, HeartbeatRequest heartbeatRequest){
        HeartbeatResponse heartbeatResponse;
        {
            std::lock_guard<std::mutex> lock(mutex_raft_info_);
            if (currentTerm_ < heartbeatRequest.term)
            {
                becomeFollowerNeedLocked(heartbeatRequest.term);
                return;
            }
            if (role_ != LEADER || currentTerm_ != heartbeatRequest.term)
            {
                return;
            }
            if (heartbeatResponse.success)
            {

            }

        }
    }
    void receiveHeartbeatRequest(HeartbeatRequest heartbeatRequest){
        {
            std::lock_guard<std::mutex> lock(mutex_raft_info_);
            if (currentTerm_ < heartbeatRequest.term)
            {
                becomeFollowerNeedLocked(heartbeatRequest.term);
                resetElectionTimeoutNeedLocked();
                return;
            }
            if (role_ != LEADER || currentTerm_ != heartbeatRequest.term)
            {
                return;
            }
            HeartbeatResponse heartbeatResponse;
            heartbeatResponse.success = true;
            heartbeatResponse.term = currentTerm_;
            heartbeatResponse.nodeId = nodeId_;
            sendHeartbeatResponse(heartbeatResponse);
        }
    }
    void log(){}
    // 锁
    std::mutex mutex_raft_info_;

    // 节点相关
    std::vector<int> nodes_;
    State state_;
    
    // 日志相关


    // 选举相关
    int nodeId_;
    int currentTerm_;
    int votedFor_;
    int electionTimeoutStart_;
    int electionTimeout_;
    int maxElectionTimeout_;
    int minElectionTimeout_;
    Role role_;
    int leaderId_;
    std::thread_selector electionTimeoutThread_;
    
    
};

}